/*
 * Cluster.h
 *
 *  Created on: Jul 28, 2011
 *      Author: nzhao
 */

#ifndef CLUSTER_H_
#define CLUSTER_H_

#include "share/Usrdef.h"
#include "core/globalvars.h"
#include "core/Spin.h"
#include "share/pulseseq.h"
#include "share/parameters.h"
#include "share/MatAlgebra.h"
#include "share/HamiForm.h"
#include "share/diagnosis.h"

#ifdef NV_CENTER
#include "special/material_NV.h"
#include "special/interaction_NV.h"
#endif

#ifdef SiC_4H
#include "special/material_4HSiC.h"
#include "special/interaction_4HSiC.h"
#endif


#define MAX_SPIN_IN_CLST	10
#define MAX_HAMI_DIM		2048		// 2 * 2^MAX_SPIN_IN_CLST
#define MAX_TIME_NUM		5000
#define MAX_PULSE_NUM		500

class cCLUSTER
{
public:
	void	initialize(cSPIN * spins,int nspin, int * spinIdx, int npulse, int total_idx, clusterHamiltonian hamiform);
	void	calc_Hamiltonian(int sign);
	void	pre_Signal();
    double	calc_Signal(double * timeseq);
	void	clear();

    void	initialize_Correlation(cSPIN * spins,int nspin, int * spinIdx, int npulse, int total_idx, clusterHamiltonian hamiform);
    void	calc_Hamiltonian_Correlation(int sign);
    void	pre_Signal_Correlation();
    double	CorrelationFunc(double tval);
    double	NoiseSpectrum(double omega);
	double  GaussianEcho( double tval );
	void	clear_Correlation();


	void	initialize_SGL(cSPIN * spins,int nspin, int * spinIdx, int npulse, int total_idx, clusterHamiltonian hamiform,  int clst_state_j);
	void	calc_Hamiltonian_SGL(int sign);
	void	pre_Signal_SGL();
	double	calc_Signal_SGL(double * timeseq);
	void	clear_SGL();
protected:
private:
	cSPIN	* spinlist;

	int	nspin;
	int	* spin_index;
        int	pulse_num;
	int	clst_idx;

	int     clster_state_J;

	double	hf1x[MAX_SPIN_IN_CLST];
	double	hf1y[MAX_SPIN_IN_CLST];
	double	hf1z[MAX_SPIN_IN_CLST];

	double	hf2x[MAX_SPIN_IN_CLST];
	double	hf2y[MAX_SPIN_IN_CLST];
	double	hf2z[MAX_SPIN_IN_CLST];

	double	locX  [MAX_SPIN_IN_CLST];
	double	locY  [MAX_SPIN_IN_CLST];
	double	locZ  [MAX_SPIN_IN_CLST];

	double  ZEROS[1];
	double	Bx [MAX_SPIN_IN_CLST];
	double	By [MAX_SPIN_IN_CLST];
	double	Bz [MAX_SPIN_IN_CLST];

	double	xx1 [MAX_SPIN_IN_CLST * MAX_SPIN_IN_CLST];
	double	yy1 [MAX_SPIN_IN_CLST * MAX_SPIN_IN_CLST];
	double	zz1 [MAX_SPIN_IN_CLST * MAX_SPIN_IN_CLST];
	double	xy1 [MAX_SPIN_IN_CLST * MAX_SPIN_IN_CLST];
	double	yz1 [MAX_SPIN_IN_CLST * MAX_SPIN_IN_CLST];
	double	zx1 [MAX_SPIN_IN_CLST * MAX_SPIN_IN_CLST];
	double	yx1 [MAX_SPIN_IN_CLST * MAX_SPIN_IN_CLST];
	double	zy1 [MAX_SPIN_IN_CLST * MAX_SPIN_IN_CLST];
	double	xz1 [MAX_SPIN_IN_CLST * MAX_SPIN_IN_CLST];

	double	xx2 [MAX_SPIN_IN_CLST * MAX_SPIN_IN_CLST];
	double	yy2 [MAX_SPIN_IN_CLST * MAX_SPIN_IN_CLST];
	double	zz2 [MAX_SPIN_IN_CLST * MAX_SPIN_IN_CLST];
	double	xy2 [MAX_SPIN_IN_CLST * MAX_SPIN_IN_CLST];
	double	yz2 [MAX_SPIN_IN_CLST * MAX_SPIN_IN_CLST];
	double	zx2 [MAX_SPIN_IN_CLST * MAX_SPIN_IN_CLST];
	double	yx2 [MAX_SPIN_IN_CLST * MAX_SPIN_IN_CLST];
	double	zy2 [MAX_SPIN_IN_CLST * MAX_SPIN_IN_CLST];
	double	xz2 [MAX_SPIN_IN_CLST * MAX_SPIN_IN_CLST];

	clusterHamiltonian  hm;
	int                 blk_num;
	int                 * blk_dim;
	HamiElement         ** matrix_Form;
	int					* need_calc;

	double              * INTERACTIONS[13];

	int	dim;

	CLD     ** C_HAMI_0;                    // hamilontian for H_B + 0.5 * ( b1 + b2 )
	CLD     ** C_HAMI_1;                    // hamilontian for H_B + Sz1 * b
	CLD     ** C_HAMI_2;                    // hamilontian for H_B + Sz2 * b
	CLD		** H_B_Mat;
	CLD		** b_Mat;

	double ** eigen_val0;
	double ** eigen_val1;
	double ** eigen_val2;
	double ** eigen_val_H_B;
	double ** eigen_val_b;
	CLD  ** eigen_vec0;
	CLD  ** eigen_vec1;
	CLD  ** eigen_vec2;
	CLD  ** eigen_vec_H_B;
	CLD  ** eigen_vec_b;

	double              B2;
//	double              BMAT[MAX_HAMI_DIM * MAX_HAMI_DIM];  // noise operator b
//	gsl_matrix_complex  * WEIGHT_MAT;

    CLD ** W_matrix;

//	gsl_complex         exp_eigen_val[MAX_HAMI_DIM * MAX_PULSE_NUM ];
    CLD	*i_phase_fact;//[MAX_HAMI_DIM * MAX_PULSE_NUM];
    CLD	*exp_eigen_val;//[MAX_HAMI_DIM * MAX_PULSE_NUM];

	CLD ** left_mat0,	** left_mat;
	CLD ** right_mat0,	** right_mat;

	CLD ** left_vec0,	** left_vec;
	CLD ** right_vec0,	** right_vec;

//	gsl_matrix_complex  * left_mat ;
//	gsl_matrix_complex  * right_mat;

	double PDD_algorithm_even(double * timeseq);
	double PDD_algorithm_odd(double * timeseq);
//	double Package_algorithm(double * timeseq);
//	double SYM_algorithm_even(double * timeseq);
//	double SYM_algorithm_odd(double * timeseq);
	double Generic_algorithm(double * timeseq);

	void set_localfield();
	void row_transform(CLD * expval);
	void W_Mat_transform(int i);

	void set_localfield_SGL();
	void row_transform_SGL(CLD * expval);
	void W_Mat_transform_SGL(int i);

    double int_cos_func(double delta_w, double tval, int npulse);
    double int_cos_function(double delta_w, double tval);
};

void calculation_cluster(cCLUSTER cluster, cSPIN * spin_list, int order_i, int idx_j, int count, double * clst_res,  double * irr_clst_res);

#endif /* CLUSTER_H_ */
